package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.search.dto.ApArticleSearchDto;
import com.heima.search.entity.ApArticleSearch;
import com.heima.search.service.IApUserSearchService;
import com.heima.search.service.IArticleSearchService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: itheima
 * @create: 2022-01-25 10:23
 */
@Service
public class ArticleSearchServiceImpl implements IArticleSearchService {

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private IApUserSearchService userSearchService;


    /**
     * ES的api风格：接口类型XxxxBuilder  一般提供 XxxxBuilders获取 XxxxBuilder
     * 根据关键字文件检索分页文章列表，根据文章发布时间倒序排序
     *
     * @param dto 入参 包含查询关键字
     * @return 文章分页列表
     * <p>
     * <p>
     * #关键字检索文章
     * GET /app_info_article/_search
     * {
     * "query": {
     * "match": {
     * "title": "李四延迟"
     * }
     * },
     * "from": 0,
     * "size": 5,
     * "sort": [
     * {
     * "publishTime": {
     * "order": "desc"
     * }
     * }
     * ]
     * }
     */
    @Override
    public ResponseResult search(ApArticleSearchDto dto) {
        try {
            //0.判断入参是否有值
            if (dto == null || StringUtils.isBlank(dto.getSearchWords())) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
            }

            //1.创建SearchRequest对象 封装检索索引库
            SearchRequest searchRequest = new SearchRequest("app_info_article");

            //2.创建SearchSourceBuilder对象 指定http请求体中各种查询参数  包含：查询方式、分页、排序、高亮、聚合
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            //2.1 设置查询方式：全文关键字检索（match匹配查询）   查询文章标题字段  设置请求体中：query参数
            searchSourceBuilder.query(QueryBuilders.matchQuery("title", dto.getSearchWords()).operator(Operator.AND));

            //2.2 设置分页  设置请求体：from size
            Long from = (dto.getPage() - 1) * dto.getSize();
            searchSourceBuilder.from(from.intValue()).size(dto.getSize());

            //2.3 设置排序  设置请求体： sort
            searchSourceBuilder.sort("publishTime", SortOrder.DESC);

            //TODO 设置高亮-作业

            //3.将SearchSourceBuilder请求参数设置到 SearchRequest对象
            searchRequest.source(searchSourceBuilder);

            //4.执行检索
            SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

            //5.处理响应数据
            SearchHits hits = response.getHits();
            //5.1. 获取总记录数
            long total = hits.getTotalHits().value;

            //5.2 获取检索到业务数据
            SearchHit[] searchHits = hits.getHits();
            //5.2.1 遍历数组获取响应业务数据
            List<ApArticleSearch> list = new ArrayList<>();
            if (searchHits != null && searchHits.length > 0) {
                for (SearchHit searchHit : searchHits) {
                    //将JSON反序列化为Java对象
                    ApArticleSearch apArticleSearch = JSON.parseObject(searchHit.getSourceAsString(), ApArticleSearch.class);
                    list.add(apArticleSearch);
                }
            }


            //TODO 异步保存用户搜索记录
            Integer userId = null;
            User user = UserThreadLocalUtil.get();
            if (user != null) {
                userId = user.getUserId();
            }
            userSearchService.saveSearchRecord(dto.getSearchWords(), userId, dto.getEquipmentId());
            //5.3 封装分页结果
            return new PageResponseResult(dto.getPage(), dto.getSize(), total, list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
